#include "wrap.h"
#include "Iec104.h"
//在多线程的时候注意不要用到exit函数，因为它是终止进程的


//----------------------------------------
uint8_t pRespone[310];
uint16_t  pSendCNT[10];
uint16_t  pRecCNT[10];

uint8_t mydataYX[16] = {1,0,0,4,2,0,0,4,3,0,0,4,4,0,0,4};
uint8_t mydataYC[12] = {1,0,1,2,0,2,3,0,3,4,0,4};
//----------------------------------------
void perr_exit(const char *s)
{
    perror(s);
    exit(1);
}
//========================================================TCP
int Accept(int fd, struct sockaddr *sa, socklen_t *salenptr)
{
    int n;

again:
    if ( (n = accept(fd, sa, salenptr)) < 0) {
        if ((errno == ECONNABORTED) || (errno == EINTR))
            goto again;
        else
            perr_exit("accept error");
    }
    return n;
}

void Bind(int fd, const struct sockaddr *sa, socklen_t salen)
{
    if (bind(fd, sa, salen) < 0)
        perr_exit("bind error");
}

void Connect(int fd, const struct sockaddr *sa, socklen_t salen)
{
    if (connect(fd, sa, salen) < 0)
        perr_exit("connect error");
}

void Listen(int fd, int backlog)
{
    if (listen(fd, backlog) < 0)
        perr_exit("listen error");
}

int Socket(int family, int type, int protocol)
{
    int n;
    if ( (n = socket(family, type, protocol)) < 0)
        perr_exit("socket error");
    return n;
}
//============================================================================

//===================================IEC104
void *do_work(void *arg)
{
    printf("sizeof CP56time2a = %d\r\n", sizeof(struct CP56time2a));
    uint8_t buf[1024];
    int len, i;
    // int ser_socket = (int )arg;//linux 64位，要用long接
     long client_socket = (long )arg;
    pthread_detach(pthread_self());//线程结束自动退出,pthread_self();获取自己的pid
    while (1) 
    {
        len = read(client_socket, buf, sizeof(buf));
        if (len <= 0)
            break;
            printf("--------------------\r\n");
            printf("len = %d\r\n",len);
            // for(int i = 0; i < len; i++)
            // {
            //          printf(" %d :buf [%d] :%x  \r\n", client_socket,i,buf[i]);
            // }
        // send_message(client_socket,(void*)buf);

        int  flag =  IEC104_CheckPkgType(buf);
        switch (flag)
        {
            case U_PKG:
            {
                uint8_t buf_send[len];
                IEC104_UPkgRespone(buf,buf_send);
                for(int i = 0; i < len; i++)
                {
                    printf(" buf [%d] :%x \r\n",i,buf_send[i]);
                }
                int size = write(client_socket,buf_send,sizeof(buf_send));
                printf("write size = %d\r\n",size);
                break;
            }
        case S_PKG:
            {
                int n = IEC104_SPkgRespone(buf,pRecCNT);
                int size = write(client_socket,pRespone,n);
                //根据上一次的I帧回复数据
                printf("write size = %d\r\n",size);
                break;
            }
            case  I_PKG:
            {
                bool flag_IPkg = true;
                uint8_t TYP = IEC104_ChkIPkgAsduType(buf);

                switch( TYP)
                {
                    case TYP_SigngleControl_2d:
                    {
                        int n = IEC104_IPkgResponeAct(buf,pRespone,pSendCNT,pRecCNT,flag_IPkg);//发送单点遥控响应帧
                        printf("IEC104_IPkgResponeAct return =%d *pSendCNT =%d  *pRecCNT = %d\r\n",n,pSendCNT[0],pRecCNT[0]);
                        int size = write(client_socket,pRespone,n);
                        printf("write size = %d\r\n",size);
                        printf("------------------------------\r\n");
                        break;
                    }
                    
                    case TYP_DoubleControl_2e:
                    {
                        int n = IEC104_IPkgResponeAct(buf,pRespone,pSendCNT,pRecCNT,flag_IPkg);//发送双点遥控响应帧
                        printf("IEC104_IPkgResponeAct return =%d *pSendCNT =%d  *pRecCNT = %d\r\n",n,pSendCNT[0],pRecCNT[0]);
                        int size = write(client_socket,pRespone,n);
                        printf("write size = %d\r\n",size);
                        printf("------------------------------\r\n");
                        break;
                    }

                    case TYP_DoubleAdjust_2f:
                    {
                        int n = IEC104_IPkgResponeAct(buf,pRespone,pSendCNT,pRecCNT,flag_IPkg);//发送双点遥调响应帧
                        printf("IEC104_IPkgResponeAct return =%d *pSendCNT =%d  *pRecCNT = %d\r\n",n,pSendCNT[0],pRecCNT[0]);
                        int size = write(client_socket,pRespone,n);
                        printf("write size = %d\r\n",size);
                        printf("------------------------------\r\n");
                        break;
                    }
                        break;
                    case TYP_FullData_64:
                    {

                        int n =IEC104_SendYX(buf,pRespone,TYP_Telesignaling_01,Reason_ReqCall_14,mydataYX,4,1);//遥信数据
                        //int n = IEC104_IPkgResponeAct(buf,pRespone,pSendCNT,pRecCNT,flag_IPkg);//发送总召数据响应帧
                        printf("IEC104_IPkgResponeAct return =%d *pSendCNT =%d  *pRecCNT = %d\r\n",n,pSendCNT[0],pRecCNT[0]);
                        int size = write(client_socket,pRespone,n);
                        printf("write size = %d\r\n",size);
                        printf("------------------------------\r\n");
                        IEC104_SendYC(buf,pRespone,TYP_Telemetry_09,Reason_ReqCall_14,mydataYC,4,1);//遥信数据
                        size = write(client_socket,pRespone,n);
                        printf("write size = %d\r\n",size);
                        break;
                    }
                        break;
                    case TYP_FullEle_65:
                    {
                        int n = IEC104_IPkgResponeAct(buf,pRespone,pSendCNT,pRecCNT,flag_IPkg);//发送总召电力响应帧
                        printf("IEC104_IPkgResponeAct return =%d *pSendCNT =%d  *pRecCNT = %d\r\n",n,pSendCNT[0],pRecCNT[0]);
                        int size = write(client_socket,pRespone,n);
                        printf("write size = %d\r\n",size);
                        printf("------------------------------\r\n");
                        break;
                    }
                    case TYP_Clock_67:
                    {
                        int n = IEC104_IPkgResponeAct(buf,pRespone,pSendCNT,pRecCNT,flag_IPkg);//发送同步时间响应帧
                        printf("IEC104_IPkgResponeAct return =%d *pSendCNT =%d  *pRecCNT = %d\r\n",n,pSendCNT[0],pRecCNT[0]);
                        int size = write(client_socket,pRespone,n);
                        printf("write size = %d\r\n",size);
                        printf("------------------------------\r\n");
                        break;
                    }
                }
            }

        }
    }
    close(client_socket);
    printf("client_socket quit\r\n");
    return 0;//只能调return 0 不能调exit 0 不然就是终止进程了
}
